package com.yan.design.java8.k7;

import com.yan.design.pojo.Uo;

import java.io.*;

/**
 * 7 io 文件流
 *   https://blog.csdn.net/m0_64996150/article/details/122817837?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166126235416782391850038%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166126235416782391850038&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-122817837-null-null.142^v42^control,185^v2^control&utm_term=io&spm=1018.2226.3001.4187
 * @author shengren.yan
 * @create 2022-08-17
 */
public class io1 {

    // io (输入、输出)
    // 流的分类： 按数据单位分：1.字节流（8bit 例视频MP3）  2.字符流（16bit 例 .txt）
    //            按流向分：1.输入流 2.输出流
    /**
     *  抽象基类       节点流              缓冲流（处理流）       转换流
     *  InputStream    FileInputStream    BufferedInputStream   InputStreamReader
     *  OutputStream   FileOutputStream   BufferedOutputStream  OutputStreamWriter
     *  Reader         FileReader         BufferedReader
     *  Writer         FileWriter         BufferedWriter
     */
    public static void main(String[] args) { }


    // 1. 非文本文件复制  - FileInputStream / FileOutputStream
    public void test1() {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("打开指定文件路径1");
            fos = new FileOutputStream("要复制到的文件路径2");

            byte[] bytes = new byte[1024]; // 读文件内容 值 或者 2048
            int len = 0; // 实际读的字节
            while ((len = fis.read(bytes)) != -1) {
                // 将文件写入
                fos.write(bytes, 0, len);  // 读到哪里，写到哪里
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 2. 文本文件复制  - Reader / Writer
    public void test2() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("打开指定文件路径1");
            fw = new FileWriter("要复制到的文件路径2");
            char[] bytes = new char[1024]; // 读文件内容 值 或者 2048
            int len = 0; // 实际读的字节
            while ((len = fr.read(bytes)) != -1) {
                // 将文件写入
                fw.write(bytes, 0, len);  // 读到哪里，写到哪里
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fr.close();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    // 3. 缓冲流处理-文本文件复制  - BufferedInputStream / BufferedOutputStream
    //   （文本文件复制同上） BufferedReader/BufferedWriter  readLine()读
    public void test3() throws Exception{
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream("打开指定文件路径1"));
            bos = new BufferedOutputStream(new FileOutputStream("要复制到的文件路径2"));
            byte[] bytes = new byte[1024]; // 读文件内容 值 或者 2048
            int len = 0; // 实际读的字节
            while ((len = bis.read(bytes)) != -1) {
                // 将文件写入
                bos.write(bytes, 0, len);  // 读到哪里，写到哪里
                bos.flush(); // 强制清空 缓冲层
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 先关闭 缓冲流，再关闭 节点流
            bis.close();
            bos.close();
        }
    }

    // 4.对象流
    // 对象序列表：将对象以二进制形式保存到磁盘中的过程就是。 对象反序列化：将磁盘中的数据读回对象中。
    public void test4() throws Exception{

        // 注意 实体需要实现  Serializable 接口 、不能序列化static和transient修饰的成员变量
        Uo o1 = new Uo("A",1);
        // 1. 对象序列化
        ObjectOutputStream oos = null;
        try {
            BufferedOutputStream bs = new BufferedOutputStream(new FileOutputStream("打开指定文件路径1/xx.dat"));
            oos = new ObjectOutputStream(bs);
            oos.writeObject(o1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            oos.close();
        }

        // 2. 对象反序列化
        ObjectInputStream ois = null;
        try {
            BufferedInputStream bi = new BufferedInputStream(new FileInputStream("打开指定文件路径1/xx.dat"));
            ois = new ObjectInputStream(bi);
            Uo object = (Uo) ois.readObject();  // 得到对象的反序列化
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            oos.close();
        }

    }

    // 5.转换流
    // 编码：字符串 - 字节数组   解码：字节数组 - 字符串
    public void test5() throws Exception{

      // 解码
      InputStream in = System.in;
      InputStreamReader isr = new InputStreamReader(in,"utf-8");
      BufferedReader bi = new BufferedReader(isr);

      // 编码
      String str = "SSS是";
      FileOutputStream fos = new FileOutputStream("/xxx.txt");
      OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
      BufferedWriter bf = new BufferedWriter(osw);
      bf.write(str);
      bf.close();

    }


    // 6.File 文件
    public void test6() throws Exception{
        // 参数：文件或目录
        File file = new File("文件路径地址/xx.txt");
        file.getName(); // 获取文件名
        file.getPath(); // 获取相对路径
        file.getAbsoluteFile(); // 获取绝对路径下的文件
        file.getAbsolutePath(); // 获取绝对路径
        file.getPath(); // 获取父路径

        File file2 = new File("文件路径地址/xx.txt");
        boolean b = file.renameTo(file2);  // 重命名 注意第一个文件必须存在

        // 文件监测
        boolean exists = file2.exists();     // 该文件是否存在
        boolean exists2 = file2.canWrite();  // 该文件是否可写
        boolean exists3 = file2.canRead();   // 该文件是否可读
        boolean exists4 = file2.isFile();    // 该文件是否是文件
        boolean exists5 = file2.isDirectory();  // 该文件是否是目录

        //
        long l = file2.lastModified(); // 该文件最后修改的时间 - 得到 毫秒值
        long l2 = file2.length();      // 该文件大小，（字节总数） 目录没有大小

        // 文件相关
        boolean newFile = file2.createNewFile(); // 新建一个文件
        boolean delete = file2.delete();         // 删除一个文件

        // 目录
        boolean mkdir = file2.mkdir();   // 新建一个目录
        boolean mkdirs = file2.mkdirs(); // 新建一个目录,如果某个目录不存在，也版本创建
        String[] list = file2.list();    // 得到当前目录下的目录和文件名称
        File[] files = file2.listFiles();// 得到当前目录下的目录和文件的对象

    }

    // 7 递归 删除文件
    public Boolean delFile( File file ) throws Exception{

        if (!file.exists()) {
            return true;
        }
        if (file.isFile()) {
            return file.delete();
        } else {
            // 是目录
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f); // 递归删除
            }
            return file.delete();
        }

    }

}
